class Simlogger
  def initialize( gloabal_log_file = nil )
    @log = []
    @level = 0

    # if that variable == nil, then we will not write output to $stdout
    # if we have file name here, then we puts shortened strings to console and
    #   append full log strings to that file
    @gloabal_log_file = gloabal_log_file

    append_to_main_log "\n ==> Logger initialized.\n\n"
  end

  # straight string addition, type will be ':log'
  def log(str)
    update( {:type => :log, :content => str} )
  end

  def update(msg_hash)
    level_in if msg_hash[:type] == :build_start

    msg_hash[:level] = @level
    msg_hash[:time] = Time.now

    @log << msg_hash

    level_out if msg_hash[:type] == :build_end

    append_to_main_log mk_string( @log.last )
  end

  def savelog( fn )
    File.open( fn, 'a'){ |f|
      f.write( @log.collect{|entry| mk_string entry }.join("\n") )
    }
    # числим лог
    @log = []
  end

  def finalize
    append_to_main_log "\n ==> Logger finalized.\n\n"
  end

private
  def level_in
    @level += 1
  end

  def level_out
    (@level += -1) if @level > 0
  end

  def append_to_main_log( str )
    if @gloabal_log_file
      puts str.shorten(75)
      File.open(@gloabal_log_file, 'a') { |l| l.puts str }
    end
  end

  def mk_string( hash )
    ( ' ' * hash[:level] * 2 ) +
    sprintf("%-15s", hash[:type].to_s) + ' :: ' +
    hash[:time].strftime("%Y-%m-%d %H:%M:%S") + ' :: ' +
    hash[:content]
  end
end

END {
  ObjectSpace.each_object(Simlogger){ |o|
    o.finalize
  }
}
